<template>
  <div :style="{ position: 'relative', minHeight: '700px' }">
    <div :style="{ padding: '0px 40px 0px 40px' }">
      <a-page-header
        :title="`${albumInfo.name}(${pagination.total})`"
        :sub-title="albumInfo.description"
        @back="back()"
      >
        <template #extra>
          <a-button class="pic-button" @click="showTags()">查看标签</a-button>
        </template>
      </a-page-header>

      <a-upload-dragger
        v-model:fileList="fileList"
        name="file"
        :multiple="true"
        :max-count="10"
        accept="image/*"
        :customRequest="uploadImage"
        @change="handleChange"
        @drop="handleDrop"
      >
        <p class="ant-upload-drag-icon">
          <inbox-outlined style="color: #3e50b5bf"></inbox-outlined>
        </p>
        <p class="ant-upload-text">点击或拖拽上传</p>
        <p class="ant-upload-hint">
          仅支持jpg/png格式且大小在2MB以内的图片，一次最多上传10张图片。
        </p>
      </a-upload-dragger>
      <a-divider :style="{ marginTop: '10px', marginBottom: '0px' }" />
    </div>

    <a-empty
      v-if="!list.length"
      description="相册中暂无照片，请上传～"
      :style="{ marginTop: '100px' }"
    />

    <div class="container" id="container">
      <a-image-preview-group>
        <div
          class="column"
          v-for="(column, index) in waterfallColumn"
          :key="`${index}${Math.random()} `"
        >
          <div
            class="item"
            v-for="(item, i) in column.columnArr"
            :key="i"
            :style="{ height: item.height + 45 + 'px', top: item.top + 'px' }"
          >
            <PictureCard
              :picid="item.picId"
              :albumid="item.albumId"
              :filesize="item.fileSize"
              :tags="item.tags"
              :filelink="item.fileLink"
              :filename="item.fileName"
              :albumList="allAlbumList"
              :tagList="allTagList"
              @on-refresh="reload()"
            />
          </div>
        </div>
      </a-image-preview-group>
    </div>
    <br />
    <div :style="{ margin: '0 auto', marginTop: '100px', textAlign: 'center' }">
      <a-spin :spinning="loading" tip="加载中..."></a-spin>
    </div>

    <a-modal v-model:visible="tagsVisible" title="所有标签" :footer="null">
      <a-tag
        v-for="(tag, index) in tagList"
        :key="index"
        :style="{ margin: '5px' }"
        >{{ tag.tagName }}</a-tag
      >
    </a-modal>
  </div>
</template>
<script lang="ts">
import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { getAlbumInfo, albumList } from '@/apis/album';
import { getPictureAlbumList, uploadPicture } from '@/apis/picture';
import { getTagList } from '@/apis/tag';
import PictureCard from './components/PictureCard.vue';
import { InboxOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import type { UploadChangeParam } from 'ant-design-vue';
import { FileType } from 'ant-design-vue/lib/upload/interface';

interface PictureType {
  status: number;
  picId: number;
  albumId: number;
  hashCode: number;
  fileName: string;
  fileLink: string;
  fileSize: number;
  tags: string | null;
  createTime: string;
  updateTime: string;
  width: number;
  height: number;
  top?: number;
}

interface AlbumType {
  name: string;
  description: string;
  size: null | number;
  albumId: number;
  isDefaultAlbum: number;
  coverLink: null | string;
  createTime: string;
  updateTime: string;
}

interface PaginationType {
  current: number;
  pageSize: number;
  total: number;
}

interface TopHeightType {
  top: number;
  height: number;
}

interface ImgColumnType {
  columnArr: Array<PictureType>;
}

interface TagType {
  tagId: number;
  tagName: string;
  updateTime: string;
  createTime: string;
}

export default defineComponent({
  components: {
    PictureCard,
    InboxOutlined
  },
  setup() {
    const router = useRouter();
    const back = () => {
      router.push('/album');
    };

    // 获取相册信息，显示页头
    const route = useRoute();
    const albumId = route.query.albumId;
    const albumInfo = reactive<AlbumType>({
      name: '',
      description: '',
      size: 0,
      albumId: 0,
      isDefaultAlbum: 0,
      coverLink: null,
      createTime: '',
      updateTime: ''
    });

    getAlbumInfo(albumId).then((res) => {
      const {
        name,
        description,
        albumId,
        isDefaultAlbum,
        coverLink,
        createTime,
        updateTime
      } = res.data;
      albumInfo.name = name;
      albumInfo.description = description;
      albumInfo.albumId = albumId;
      albumInfo.isDefaultAlbum = isDefaultAlbum;
      albumInfo.coverLink = coverLink;
      albumInfo.createTime = createTime;
      albumInfo.updateTime = updateTime;
    });

    const allAlbumList = ref([]);

    albumList().then((res: any) => {
      allAlbumList.value = res.data.list;
    });

    const allTagList = ref([]);

    getTagList().then((res) => {
      allTagList.value = res.data.list;
    });

    // 分页配置，记载每次瀑布流下拉要获取的图片
    const pagination = reactive<PaginationType>({
      current: 1,
      pageSize: 10,
      total: 0
    });

    // 初始化照片列表
    const list = reactive<Array<PictureType>>([]);

    // 初始化瀑布流每列
    const waterfallColumn: Array<ImgColumnType> = reactive([]);

    // 图片宽度
    const imgWidth: number = 250;

    // 最小高度列
    const minHeightIndexArr: Array<number> = reactive([]);

    const getMinHeight = (arr: Array<TopHeightType>) => {
      const a = [];
      for (let i = 0; i < arr.length; i++) {
        a.push(arr[i].height + arr[i].top);
      }
      return Math.min.apply(null, a);
    };

    // 获取最小高度的图片index
    const getMinIndex = (val: number) => {
      for (let i = 0; i < waterfallColumn.length; i++) {
        const height =
          waterfallColumn[i].columnArr[waterfallColumn[i].columnArr.length - 1]
            .height;
        const top =
          waterfallColumn[i].columnArr[waterfallColumn[i].columnArr.length - 1]
            .top;
        if (
          typeof height === 'number' &&
          typeof top === 'number' &&
          height + top === val
        ) {
          minHeightIndexArr.push(i);
        }
      }
    };

    const loading = ref<boolean>(false);

    // 重新加载
    const reload = () => {
      pagination.current = 1;
      pagination.pageSize = 10;
      loading.value = true;
      getPictureAlbumList(
        albumId,
        pagination.current,
        pagination.pageSize
      ).then((res) => {
        list.splice(0, list.length);
        list.push.apply(list, res.data.list);
        pagination.total = res.data.total;
        pagination.current++;
        loading.value = false;
        nextTick(() => {
          init();
        });
      });
    };

    // 加载相册没页照片list
    const refresh = () => {
      console.log(list.length, pagination.total);
      if (list.length !== 0 && list.length === pagination.total) {
        message.warn('已经没有图片啦～');
      } else {
        loading.value = true;

        getPictureAlbumList(
          albumId,
          pagination.current,
          pagination.pageSize
        ).then((res) => {
          list.push.apply(list, res.data.list);
          pagination.total = res.data.total;
          pagination.current++;
          loading.value = false;
          init();
        });
      }
    };

    // 生成瀑布流
    const init = () => {

      // 初始化瀑布流的数组
      waterfallColumn.splice(0, waterfallColumn.length);

      // 获取图片的长度
      const contentLen = list.length;

      // 根据可视区域的宽度判断需要几列
      const cWidth = document.getElementById('container')!.clientWidth;

      // 假设图片宽度为250px
      const cLen = Math.floor((cWidth - 50) / imgWidth);

      // 初始化每一列的第一行元素
      for (let i = 0; i < cLen; i++) {
        if (i < list.length) {
          const {
            picId,
            status,
            albumId,
            hashCode,
            fileName,
            fileLink,
            fileSize,
            height,
            width,
            top,
            tags,
            createTime,
            updateTime
          } = list[i];
          const imgData: PictureType = {
            picId,
            status,
            albumId,
            hashCode,
            fileName,
            fileLink,
            fileSize,
            height,
            width,
            top,
            tags,
            createTime,
            updateTime
          };
          imgData.height = (imgWidth / imgData.width) * imgData.height;
          imgData.top = 0; // 预设距离顶部值为0
          waterfallColumn.push({ columnArr: [imgData] });
        } else {
          waterfallColumn.push({ columnArr: [] });
        }
      }

      // 对剩余元素的判断，应该放到哪一列
      for (let index = cLen; index < contentLen; index++) {
        minHeightIndexArr.splice(0, minHeightIndexArr.length);
        const arr: Array<TopHeightType> = []; // 找到高度最小的一列，可能有多个
        let minHeight = 0; // 高度最小的一列的高度
        let pushIndex = 0; // 高度最小的一列所在位置的索引
        for (let i = 0; i < waterfallColumn.length; i++) {
          const height =
            waterfallColumn[i].columnArr[
              waterfallColumn[i].columnArr.length - 1
            ].height;
          const top =
            waterfallColumn[i].columnArr[
              waterfallColumn[i].columnArr.length - 1
            ].top;
          if (typeof height === 'number' && typeof top === 'number') {
            arr.push({ height, top });
          }
        }
        minHeight = getMinHeight(arr);
        getMinIndex(minHeight);

        if (minHeightIndexArr.length > 0) {
          pushIndex = Math.min.apply(null, minHeightIndexArr); // 出现高度一样的，去索引最小的
        }
        const {
          picId,
          status,
          albumId,
          hashCode,
          fileName,
          fileLink,
          fileSize,
          height,
          width,
          top,
          tags,
          createTime,
          updateTime
        } = list[index];
        const imgData: PictureType = {
          picId,
          status,
          albumId,
          hashCode,
          fileName,
          fileLink,
          fileSize,
          height,
          width,
          top,
          tags,
          createTime,
          updateTime
        };
        imgData.height = (imgWidth / imgData.width) * imgData.height;
        imgData.top = minHeight + 20; // 预设距离顶部值为0
        waterfallColumn[pushIndex].columnArr.push(imgData);
      }
    };

    const tagsVisible = ref<boolean>(false);

    const tagList = reactive<Array<TagType>>([]);

    const showTags = () => {
      getTagList().then((res) => {
        tagList.splice(0, tagList.length);
        tagList.push.apply(tagList, res.data.list);
        tagsVisible.value = true;
      });
    };

    const fileList = ref<Array<FileType>>([]);

    // 上传照片
    const handleChange = (info: UploadChangeParam) => {
      const status = info.file.status;
      if (status !== 'uploading') {
        console.log(info.file, info.fileList);
      }
      if (status === 'done') {

        // message.success(`${info.file.name} file uploaded successfully.`);
      } else if (status === 'error') {

        // message.error(`${info.file.name} file upload failed.`);
      }
    };

    const uploadImage = (options: any) => {
      const file = options.file;
      const formData = new FormData();
      formData.append('albumId', albumInfo.albumId + '');
      formData.append('pictures', file);

      uploadPicture(formData).then((res) => {
        message.success('上传照片成功！');
        fileList.value = [];
        reload();
      });
    };

    onMounted(async() => {
      refresh();
      window.onresize = () => {
        init();
      };

      document.onscroll = (e: any) => {

        // const clientH =
        //   document.documentElement.clientHeight || document.body.clientHeight;

        // const top =
        //   e.target.documentElement.scrollTop || e.target.body.scrollTop;
        // const height =
        //   e.target.documentElement.scrollHeight || e.target.body.scrollHeight;

        // 获取滚动的距离
        const scrollTop = document.documentElement.scrollTop;

        // 获取滚动的高度（获取整个html的高度）
        const scrollHeight = document.documentElement.scrollHeight;

        // 获取屏幕(浏览器)高度
        const clienHeight = document.documentElement.clientHeight;

        // 滚动的距离 + 屏幕高度 - 内容高度 >= 0 表示滚动到底部了      (下拉加载判断条件)
        if (scrollTop + clienHeight - scrollHeight == 0) {
          refresh();
        }

        // if (top + clientH === height) {

        //   console.log(route);
        //   console.log('相册模块下拉加载照片');
        //   refresh();
        // }
      };
    });

    return {
      list,
      back,
      albumInfo,
      allTagList,
      allAlbumList,
      init,
      waterfallColumn,
      pagination,
      handleChange,
      fileList,
      uploadImage,
      handleDrop: (e: DragEvent) => {
        console.log(e);
      },
      loading,
      tagsVisible,
      showTags,
      tagList,
      reload
    };
  }
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
div,
p {
  margin: 0;
  padding: 0;
}
.container {
  margin: 0 auto;
  padding-bottom: 20px;
  display: flex;
  // justify-content: space-around;
  justify-content: center;
  /* background: pink; */
  transition: all 0.5s ease-in-out;
}
.item {
  width: 250px;
  color: #000;
  // margin-top: 20px;
  margin: 10px 8px 10px 8px;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all 0.5s ease-in-out;
}
.loading {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.pic-button {
  display: inline-block;
  margin-left: 20px;
}
</style>
